package controllers

import (
	"encoding/json"
	"fmt"
	adminService "greenbeeadmin/controllers/admin/service"
	"greenbeeadmin/models"
	"image/color"
	"math"
	"net/url"
	"strconv"

	greenbeeUtils "greenbeeadmin/controllers/greenbee/utils"

	"github.com/beego/beego/v2/adapter/context"
	"github.com/beego/beego/v2/client/orm"
	beego "github.com/beego/beego/v2/server/web"
	"github.com/mojocn/base64Captcha"
)

type MainBaseController struct {
	beego.Controller
}

// json返回格式 结构体
type ReturnMsg struct {
	Code  int         `json:"code"`
	Msg   string      `json:"msg"`
	Count int         `json:"count"`
	Data  interface{} `json:"data"`
}

// 返回成功json数据
func (c *MainBaseController) SuccessJson(code int, data interface{}, count int) {

	res := ReturnMsg{
		code, "success", count, data,
	}
	c.Data["json"] = res
	c.ServeJSON() //对json进行序列化输出
	c.StopRun()
}

func (c *MainBaseController) ErrorJson(code int, msg string, count int, data interface{}) {

	res := ReturnMsg{
		code, msg, count, data,
	}

	c.Data["json"] = res
	c.ServeJSON() //对json进行序列化输出
	c.StopRun()
}

// admin基类结构体
type AdminBaseController struct {
	MainBaseController
}

/** 该struct处理页面错误请求 start **/
type ErrorController struct {
	AdminBaseController
}

// 404页面替换
func (c *ErrorController) Error404() {
	c.TplName = "error/404.html"
}

// admin 404
type AdminErr404Page struct {
	AdminBaseController
}

func (c *AdminErr404Page) Get() {
	c.TplName = "error/404.html"
}

/** 该struct处理页面错误请求 end **/

/**
 * @description: 获取分页html
 * @param {string} page_url 当前页面url
 * @param {float64} page  当前页
 * @param {float64} limit  每页显示条数
 * @param {int64} cnt 总条数
 * @param {...map[int]map[string]string} url_param  拼接url的参数
 * @return {*}
 */
func (c *MainBaseController) GetPageHtml(page_url string, page, limit float64, cnt int64, url_param ...map[int]map[string]string) float64 {
	//分页
	var offset float64

	//offset = 0
	pages := make(map[string]interface{})
	show_page := ""
	pages["page"] = page
	pages["limit"] = limit
	cntss := float64(cnt)
	total_page := math.Ceil(cntss / limit)
	pages["total_page"] = total_page
	//当前页
	current_page := int(page)
	if current_page > int(total_page) {
		current_page = int(total_page)
	}
	//偏移量计算
	page = float64(page - 1)
	if page <= 0 {
		page = 0
	}
	if page >= total_page {
		page = total_page - 1
	}
	offset = page * limit //计算偏移量
	pages["offset"] = offset

	//拼接url参数
	url_params := ""
	if len(url_param) > 0 {
		for _, re := range url_param {
			//fmt.Println(re)
			for _, rr := range re {
				url_params += "&" + rr["key"] + "=" + rr["value"]
			}

		}
	}

	if total_page > 1 {
		//生成 分页html
		//page_url := "/admin/user"

		//上一页
		if current_page > 1 {
			pre_num := current_page - 1
			str_pre_num := fmt.Sprintf("%d", pre_num)
			show_page += "<li class='prev '>"
			show_page += "	<a href='" + page_url + "?page=" + str_pre_num + url_params + "'>"
			show_page += "	<i class='ace-icon fa fa-angle-double-left'></i>"
			show_page += "	</a>"
			show_page += "</li>"
		}
		//页码
		active_str := ""
		//分页数量大于5计算分页显示的范围
		var show_page_start int
		var show_page_end int
		if current_page >= 5 {
			show_page_start = int(current_page - 2)
			show_page_end = int(current_page + 2)
			if show_page_end > int(total_page) {
				show_page_end = int(total_page)
			}
		}
		for i := 1; i <= int(total_page); i++ {
			str_num := fmt.Sprintf("%d", i)
			active_str = ""
			if int(i) == current_page {
				active_str = "class='active'"
			}
			//分页数量大于5计算分页显示的范围
			if current_page >= 5 {
				if i == 1 {
					show_page += "<li >"
					show_page += "	<a href='" + page_url + "?page=" + str_num + url_params + "'>" + str_num + "</a>"
					show_page += "</li>"

					show_page += "<li >"
					show_page += "	<a >...</a>"
					show_page += "</li>"
				}
				if i >= show_page_start && i <= show_page_end {
					show_page += "<li " + active_str + ">"
					show_page += "	<a href='" + page_url + "?page=" + str_num + url_params + "'>" + str_num + "</a>"
					show_page += "</li>"
				}

				if i == int(total_page) && show_page_end < int(total_page) {
					show_page += "<li >"
					show_page += "	<a >...</a>"
					show_page += "</li>"

					show_page += "<li >"
					show_page += "	<a href='" + page_url + "?page=" + str_num + url_params + "'>" + str_num + "</a>"
					show_page += "</li>"
				}

			} else {
				if i <= 6 {
					show_page += "<li " + active_str + ">"
					show_page += "	<a href='" + page_url + "?page=" + str_num + url_params + "'>" + str_num + "</a>"
					show_page += "</li>"
				}

				if i == int(total_page) && int(total_page) > 7 {
					show_page += "<li >"
					show_page += "	<a >...</a>"
					show_page += "</li>"

					show_page += "<li >"
					show_page += "	<a href='" + page_url + "?page=" + str_num + url_params + "'>" + str_num + "</a>"
					show_page += "</li>"
				}

			}

		}

		//下一页
		if current_page < int(total_page) {
			nex_num := current_page + 1
			str_next_num := fmt.Sprintf("%d", nex_num)
			show_page += "<li class='next'>"
			show_page += "	<a href='" + page_url + "?page=" + str_next_num + url_params + "'>"
			show_page += "	<i class='ace-icon fa fa-angle-double-right'></i>"
			show_page += "	</a>"
			show_page += "</li>"
		}
	}

	c.Data["pages"] = pages
	c.Data["show_page"] = show_page
	return offset
}

// 获取系统设置
func (c *MainBaseController) GetSystemSetingData() (models.SystemSetting, error) {
	o := orm.NewOrm()
	data := models.SystemSetting{Types: "system"}
	err := o.Read(&data, "Types")
	if err == orm.ErrNoRows {
		fmt.Println("查询不到")
	} else if err == orm.ErrMissPK {
		fmt.Println("找不到主键")
	}
	return data, err
}

// 邮箱配置参数
type EmailSystemData struct {
	Server_host string `json:"server_host"`
	Server_port string `json:"server_port"`
	From_email  string `json:"from_email"`
	From_passwd string `json:"from_passwd"`
}

// 获取系统邮箱设置
func (c *MainBaseController) GetSystemEmailSetingData() (EmailSystemData, error) {
	o := orm.NewOrm()
	system_data := models.SystemSetting{Types: "email"}
	err := o.Read(&system_data, "Types")
	if err == orm.ErrNoRows {
		fmt.Println("查询不到")
	} else if err == orm.ErrMissPK {
		fmt.Println("找不到主键")
	}
	//解析邮箱配置参数
	var email_data EmailSystemData
	if len(system_data.Gonggao) > 0 {
		json.Unmarshal([]byte(system_data.Gonggao), &email_data)
	}

	return email_data, err
}

// 图片验证码 struct
type CmfCaptchaController struct {
	MainBaseController
}

// 验证码默认存储对象，数量10240，有效时间10分钟
var CaptchaStore = base64Captcha.DefaultMemStore

func (c *CmfCaptchaController) Get() {
	//接收要展示的验证码类型 默认 数学验证码
	captcha_type := c.GetString("type", "")
	// 配置项
	Height := 70
	Width := 240
	NoiseCount := 0
	ShowLineOptions := base64Captcha.OptionShowHollowLine
	BgColor := &color.RGBA{
		R: 144,
		G: 238,
		B: 144,
		A: 10,
	}
	var FontsStorage base64Captcha.FontsStorage
	var Fonts []string

	//根据条件获取验证码
	var err error
	var b64s string
	var id string
	if captcha_type == "character" {
		// 获取数字+字母验证码
		id, b64s, err = CaptMakeString(Height, Width, NoiseCount, ShowLineOptions, BgColor, FontsStorage, Fonts)
	} else {
		// 获取数学验证码
		id, b64s, err = CaptMath(Height, Width, NoiseCount, ShowLineOptions, BgColor, FontsStorage, Fonts)
	}
	// 构造响应信息
	var response = struct {
		Code       int    `json:"code"`
		CaptchaID  string `json:"captcha_id"`
		CaptchaImg string `json:"captcha_img"`
	}{
		1,
		id,
		b64s,
	}
	if err != nil {
		//验证码获取失败
		response.Code = 0
	}

	// 返回响应
	c.Data["json"] = response
	c.ServeJSON()
}

// 生成 数学类型的验证码
func CaptMath(Height, Width, NoiseCount, ShowLineOptions int, BgColor *color.RGBA, FontsStorage base64Captcha.FontsStorage, Fonts []string) (string, string, error) {
	// 这里用的是Math类型的验证码
	driver := base64Captcha.NewDriverMath(Height, Width, NoiseCount, ShowLineOptions, BgColor, FontsStorage, Fonts)
	captcha := base64Captcha.NewCaptcha(driver, CaptchaStore)
	id, b64s, err := captcha.Generate()
	return id, b64s, err
}

// 生成数字+字母验证码
func CaptMakeString(Height, Width, NoiseCount, ShowLineOptions int, BgColor *color.RGBA, FontsStorage base64Captcha.FontsStorage, Fonts []string) (string, string, error) {
	var driver base64Captcha.Driver
	var driverString base64Captcha.DriverString

	// 配置验证码信息
	captchaConfig := base64Captcha.DriverString{
		Height:          Height,
		Width:           Width,
		NoiseCount:      NoiseCount,
		ShowLineOptions: ShowLineOptions,
		Length:          4,
		Source:          "1234567890qwertyuioplkjhgfdsazxcvbnm",
		BgColor:         BgColor,
		Fonts:           Fonts,
	}

	driverString = captchaConfig
	driver = driverString.ConvertFonts()
	captcha := base64Captcha.NewCaptcha(driver, CaptchaStore)
	lid, lb64s, lerr := captcha.Generate()
	return lid, lb64s, lerr
}

// 管理员是否登陆判定
func IsLogin(ctx *context.Context) bool {
	// 异常处理/恢复
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
			return
		}
	}()
	user := ctx.Input.Session("user")
	if user == nil {
		//获取 登陆自动续期 cookie信息
		admin_id := ""
		cooikes := ctx.Input.Cookie("automatic_login")
		cooike_datas, err := url.QueryUnescape(cooikes)
		//fmt.Println(cooike_datas)
		if cooike_datas != "" && err == nil {
			// AES decryption
			system_key, _ := beego.AppConfig.String("greenbee_system_key")
			key := []byte(system_key) //加密key
			adm_id, err := greenbeeUtils.Base64AESCBCDecrypt(cooike_datas, key)
			if err != nil {
				return false
			}
			//fmt.Println(string(adm_id))
			admin_id = string(adm_id)
		}

		if admin_id != "" {
			// TODO 登陆跳过
			id, _ := strconv.Atoi(admin_id)
			o := orm.NewOrm()
			user_admin := models.AdminUser{Id: id}
			err = o.Read(&user_admin, "Id")
			if err == nil {
				err := ctx.Input.CruSession.Set(ctx.Request.Context(), "user", user_admin)
				if err != nil {
					var adminUserService adminService.AdminUserService
					authorizationUrls := adminUserService.GetUserAuthorizationUrls(user_admin.Id)
					ctx.Input.CruSession.Set(ctx.Request.Context(), "userAuthorizationUrls", authorizationUrls)
				}
			}
			// 登陆跳过 end
		}
	}
	//重新获取用户session
	user = ctx.Input.Session("user")
	return user != nil
}

// 系统是否安装判定
func IsInstalled() bool {
	// 异常处理/恢复
	defer func() {
		if err := recover(); err != nil {
			fmt.Println(err)
			return
		}
	}()
	/** 判断系统安装状态 **/

	//根据配置文件判断
	is_install, _ := beego.AppConfig.String("is_install")
	if is_install == "true" {
		return true
	}

	//二次判断，根据文件判断
	file_path := "conf/install.lock"
	is_exist := greenbeeUtils.FileExists(file_path)
	return is_exist
}
